
class Grid {
    constructor() {
        this.edit = false;
        this.grid = document.querySelector(".grid");
        this.numberCount = 0;
        this.gridNums = new Array(9).fill(0).map(_ => {
            return new Array(9).fill(0).map(_ => ({
                number: undefined,
                isFixed: false
            }))
        })
        this.initGrid();
    }
    resetGrid() {
        this.edit = false;
        this.grid.classList.remove("edit");
        this.numberCount = 0;
        this.gridNums = new Array(9).fill(0).map(_ => {
            return new Array(9).fill(0).map(_ => ({
                number: undefined,
                isFixed: false
            }))
        })
        document.querySelector('#edit').innerText = "编辑数独";
        this.initGrid()
    }
    addEditEvent() {
        this.grid.onclick = (e) => {
            if (!this.edit) return;
            const { x, y } = e.target.dataset;
            const n = parseInt(window.prompt("请输入一个1-9之间的数字"));
            if (isNaN(n) || n < 1 || n > 9) {
                alert("请输入合法数字");
                return;
            }
            this.addNum(x, y, n);
            this.initGrid();
        }
    }
    initGrid() {
        this.grid.onclick = null;
        this.grid.innerHTML = "";
        this.gridNums.forEach((item, i) => {
            item.forEach((op, j) => {
                const dom = document.createElement('div');
                dom.dataset.x = i;
                dom.dataset.y = j;
                dom.classList.add("block");
                dom.style.backgroundColor = this.getCssBgColor(i,j);
                if (op.isFixed) dom.classList.add("fix");
                if (op.number) dom.innerText = op.number;
                this.grid.appendChild(dom)
            })
        })
        this.addEditEvent();
    }
    addNum(i, j, n, isFixed = true) {
        this.gridNums[i][j] = { number: n, isFixed };
        this.numberCount++;
        return this;
    }
    getCssBgColor(x, y) {
        let arr = [
            { s: 0, e: 0, bg: '#d8d8d8' },
            { s: 0, e: 3, bg: '#f2f2f2' },
            { s: 0, e: 6, bg: '#d8d8d8' },
            { s: 3, e: 0, bg: '#f2f2f2' },
            { s: 3, e: 3, bg: '#d8d8d8' },
            { s: 3, e: 6, bg: '#f2f2f2' },
            { s: 6, e: 0, bg: '#d8d8d8' },
            { s: 6, e: 3, bg: '#f2f2f2' },
            { s: 6, e: 6, bg: '#d8d8d8' }];
        let index = -1;
        for (let i = 0; i < 9; i++) {
            const { s, e } = arr[i]
            if ((x >= s && x < s + 3) && (y >= e && y < e + 3)) {
                index = i;
                break;
            }
        }
        return arr[index].bg;
    }
    // 检查横纵向
    checkHengZhong(x, y, n) {
        for (let i = 0; i < 9; i++) {
            if (this.gridNums[x][i].number === n) return false;
        }
        for (let i = 0; i < 9; i++) {
            if (this.gridNums[i][y].number === n) return false;
        }
        return true;
    }
    // 检查方格
    checkModule(x, y, n) {
        let arr = [{ s: 0, e: 0 }, { s: 0, e: 3 }, { s: 0, e: 6 }, { s: 3, e: 0 }, { s: 3, e: 3 }, { s: 3, e: 6 }, { s: 6, e: 0 }, { s: 6, e: 3 }, { s: 6, e: 6 }];
        let index = -1;
        for (let i = 0; i < 9; i++) {
            const { s, e } = arr[i]
            if ((x >= s && x < s + 3) && (y >= e && y < e + 3)) {
                index = i;
                break;
            }
        }
        if (index === -1) return true;
        const { s, e } = arr[index];
        for (let k = s; k < s + 3; k++) {
            for (let l = e; l < e + 3; l++) {
                if (this.gridNums[k][l].number === n) return false;
            }
        }
        return true;
    }
    analyze(n) {
        if (n >= 81) {
            this.initGrid();
            return;
        }
        for (let i = 0; i < 9; i++) {
            for (let j = 0; j < 9; j++) {
                if (!this.gridNums[i][j].isFixed && !this.gridNums[i][j].number) {
                    for (let k = 1; k <= 9; k++) {
                        if (this.checkHengZhong(i, j, k) && this.checkModule(i, j, k)) {
                            this.gridNums[i][j] = { number: k, isFixed: false };
                            this.analyze(n + 1)
                            this.gridNums[i][j] = { number: undefined, isFixed: false };
                        }
                    }
                    return;
                }
            }
        }
    }
    startGame() {
        this.initGrid();
        this.analyze(this.numberCount);
    }
}

var game = new Grid();

document.querySelector('#edit').addEventListener("click", (e) => {
    if (game.edit) {
        game.edit = false;
        game.grid.classList.remove("edit");
        e.target.innerText = "编辑数独"
    } else {
        game.edit = true;
        game.grid.classList.add("edit")
        e.target.innerText = "保存数独"
    }
})
document.querySelector('#reset').addEventListener("click", () => {
    game.resetGrid()
})
document.querySelector('#start').addEventListener("click", () => {
    game.edit = false;
    game.grid.classList.remove("edit");
    document.querySelector('#edit').innerText = "编辑数独"
    game.startGame()
})